// Learn cc.Class:
//  - [Chinese] http://docs.cocos.com/creator/manual/zh/scripting/class.html
//  - [English] http://www.cocos2d-x.org/docs/creator/en/scripting/class.html
// Learn Attribute:
//  - [Chinese] http://docs.cocos.com/creator/manual/zh/scripting/reference/attributes.html
//  - [English] http://www.cocos2d-x.org/docs/creator/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - [Chinese] http://docs.cocos.com/creator/manual/zh/scripting/life-cycle-callbacks.html
//  - [English] http://www.cocos2d-x.org/docs/creator/en/scripting/life-cycle-callbacks.html

import { _decorator, Component, Node, Vec3, CCBoolean } from "cc";
import { roadPoint } from "./roadPoint";
import { fightConstants } from "./fightConstants";
import { resourceUtil } from "../framework/resourceUtil";
import { poolManager } from "../framework/poolManager";
import { clientEvent } from "../framework/clientEvent";
import i18n from "../i18nMaster/runtime-scripts/LanguageData";
const { ccclass, property } = _decorator;
// import {writeFile} from 'fs';


@ccclass("fightMap")
export class fightMap extends Component {
    /* class member could be defined like this */
    // dummy = '';

    /* use `property` decorator if your want the member to be serializable */
    // @property
    // serializableDummy = 0;
    @property({type: cc.Node, displayName: "各路线起点"})
    public path:Node[] = [];

    _isExporting: boolean = false
    @property({displayName: '导出'})
    get Export () {
        return this._isExporting;
    }
    
    objMap: any
    objExport: any
    _progressListener: Function
    _completeListener: Function
    curProgress: number
    maxProgress: number

    levelProgressCnt: number = 0; //关卡总进度

    set Export (value) {
        if (value && CC_EDITOR) {
            //导出
            this._isExporting = true;
            this._export();
        }
    }

    start () {
        // Your initialization goes here.
        
    }

    _export () {
        
        //根据地图文件导出对应配置文件
        let name = this.node.name;

        this.objExport = {};

        //看采用的地面是什么
        this.parseDetailByType('plane');

        //获取路面所用模型
        this.parseDetailByType('road');

        //获取所有建筑
        this.parseDetailByType('house');

        //获取所有树木
        this.parseDetailByType('tree');

        //获取所有路标
        this.parseDetailByType('sign');

        //获取所有路径
        //路径解析方式比较复杂
        this.parsePath();

        let projectPath = window.cce.project;
        var fs = require('fs');


        let content = JSON.stringify(this.objExport);
        if (window['LZString']) {
            console.log('zip');
            content = window['LZString'].compressToEncodedURIComponent(content);
        }
        
        let fileName =`${projectPath}/assets/resources/gamePackage/map/config/${name}.zip`;
        fs.writeFile(fileName, content, (err)=>{
            this._isExporting = false;

            console.log("writeFile success", err);
        });
    }

    //分析行走路径
    parsePath () {
        let nodePathParent = this.node.getChildByName('path');
        let objDetail = {
            name: nodePathParent.name,
            pX: nodePathParent.position.x,
            pY: nodePathParent.position.y,
            pZ: nodePathParent.position.z,
            children: []
        }
        
        //先搜索有几条路径
        

        //根据this.path属性来获得配置的几条路径的点
        for (let idxStart = 0; idxStart < this.path.length; idxStart++) {
            let nodePoint = this.path[idxStart];
            let nodePath = nodePoint.parent;

            let objPath = {
                name: nodePath.name,
                pX: nodePath.position.x,
                pY: nodePath.position.y,
                pZ: nodePath.position.z,
                path: this.parseRoadPoint(nodePoint)
            }

            objDetail.children.push(objPath);
        }

        this.objExport[objDetail.name] = objDetail;
    }

    parseRoadPoint (nodePoint) {
        if (!nodePoint) {
            return null;
        }

        let point = nodePoint.getComponent(roadPoint);

        let objChild = {
            name: nodePoint.name,
            pX: Number(nodePoint.position.x.toFixed(3)),
            pY: Number(nodePoint.position.y.toFixed(3)),
            pZ: Number(nodePoint.position.z.toFixed(3)),
            rX: Number(nodePoint.eulerAngles.x.toFixed(3)),
            rY: Number(nodePoint.eulerAngles.y.toFixed(3)),
            rZ: Number(nodePoint.eulerAngles.z.toFixed(3)),
            sX: Number(nodePoint.scale.x.toFixed(3)),
            sY: Number(nodePoint.scale.y.toFixed(3)),
            sZ: Number(nodePoint.scale.z.toFixed(3)),
            type: point.type,
            next: this.parseRoadPoint(point.next),
            moveType: point.moveType,
            clockwise: point.clockwise,
            direction: point.direction,
            delayTime: point.delayTime,
            genInterval: point.genInterval,
            carSpeed: point.carSpeed,
            cars: point.cars,
        };

        return objChild;
    }

    parseDetailByType (type) {
        let nodeDetail = this.node.getChildByName(type);
        if (!nodeDetail) {
            console.log(`this map don't have ${type}`);
            return;
        }

        let objDetail = {
            name: nodeDetail.name,
            pX: nodeDetail.position.x,
            pY: nodeDetail.position.y,
            pZ: nodeDetail.position.z,
            children: []
        }

        for (let idx = 0; idx < nodeDetail.children.length; idx++) {
            let child = nodeDetail.children[idx];
            let objChild = this.parseChildDetail(child, type);
            
            objDetail.children.push(objChild);
        }

        this.objExport[objDetail.name] = objDetail;
    }

    parseChildDetail (child, type) {
        let objChild = {
            name: child.name,
            pX: Number(child.position.x.toFixed(3)),
            pY: Number(child.position.y.toFixed(3)),
            pZ: Number(child.position.z.toFixed(3)),
            rX: Number(child.eulerAngles.x.toFixed(3)),
            rY: Number(child.eulerAngles.y.toFixed(3)),
            rZ: Number(child.eulerAngles.z.toFixed(3)),
            sX: Number(child.scale.x.toFixed(3)),
            sY: Number(child.scale.y.toFixed(3)),
            sZ: Number(child.scale.z.toFixed(3)),
        };

        return objChild;
    }

    //构建地图
    buildMap (jsonInfo: any, progressCb: Function, completeCb: Function) {
        this._progressListener = progressCb;
        this._completeListener = completeCb;
        this.objMap = jsonInfo;
        //构建地面
        this.curProgress = 0;
        this.maxProgress = 6;

        this.buildModel('plane');
        this.buildModel('road');
        this.buildModel('tree');
        this.buildModel('house');
        this.buildModel('sign');
        this.buildPath();
    }

    buildModel (type) {
        if (!this.objMap.hasOwnProperty(type)) {
            //继续
            this.triggerFinished(type);
            return;
        }

        //搜索所需资源
        let arrName = [];
        let objPlane = this.objMap[type];
        for (let idx = 0; idx < objPlane.children.length; idx++) {
            let name = objPlane.children[idx].name;
            if (arrName.indexOf(name) === -1) {
                arrName.push(name);
            }
        }

        let dictPrefab = {};
        resourceUtil.getMapObjs(type, arrName, ()=>{}, (err, arrPrefabs)=>{
            if (err) {
                console.error(err);
                return;
            }

            for (let idx = 0; idx < arrPrefabs.length; idx++) {
                let prefab = arrPrefabs[idx];
                dictPrefab[prefab.data.name] = prefab;
            }

            //开始创建
            //先创建父节点
            let nodeParent = new Node(type);
            nodeParent.parent = this.node;
            nodeParent.setPosition(new Vec3(objPlane.pX, objPlane.pY, objPlane.pZ));
            
            //开始创建子节点
            for (let idx = 0; idx < objPlane.children.length; idx++) {
                let child = objPlane.children[idx];
                let prefab = dictPrefab[child.name];
                let node = poolManager.instance.getNode(prefab, nodeParent);
                node.setPosition(child.pX, child.pY, child.pZ);
                node.eulerAngles = new Vec3(child.rX, child.rY, child.rZ);
                node.setScale(child.sX, child.sY, child.sZ);
            }

            this.triggerFinished(type);
        });
    }

    buildPath () {
        if (!this.objMap.hasOwnProperty('path')) {
            //继续
            return;
        }

        this.path = [];
        this.levelProgressCnt = 0;
        let objPathRoot = this.objMap.path;
        let nodePathRoot = new Node('path');
        nodePathRoot.parent = this.node;
        nodePathRoot.setPosition(objPathRoot.pX, objPathRoot.pY, objPathRoot.pZ);

        //开始创建各条路径
        for (let idx = 0; idx < objPathRoot.children.length; idx++) {
            let objPath = objPathRoot.children[idx];
            let nodePath = new Node(objPath.name);
            nodePath.parent = nodePathRoot;
            nodePath.setPosition(objPath.pX, objPath.pY, objPath.pZ);


            //开始递归创建路径
            let start = this.createRoadPoint(objPath.path, nodePath);
            this.path.push(start);
        }

        this.triggerFinished('path');
    }

    createRoadPoint (objPoint, parent) {
        if (!objPoint) {
            return null;
        }

        let nodeRoadPoint = new Node(objPoint.name);
        nodeRoadPoint.parent = parent;
        nodeRoadPoint.setPosition(objPoint.pX, objPoint.pY, objPoint.pZ);
        nodeRoadPoint.setScale(objPoint.sX, objPoint.sY, objPoint.sZ);
        nodeRoadPoint.eulerAngles = new Vec3(objPoint.rX, objPoint.rY, objPoint.rZ);
        let point = nodeRoadPoint.addComponent(roadPoint);
        point.type = objPoint.type;
        point.moveType = objPoint.moveType;
        point.clockwise = objPoint.clockwise;
        point.direction = objPoint.direction;
        point.delayTime = objPoint.delayTime;
        point.genInterval = objPoint.genInterval;
        point.carSpeed = objPoint.carSpeed;
        point.cars = objPoint.cars;

        if (point.type === fightConstants.ROAD_POINT_TYPE.PLATFORM) {
            this.levelProgressCnt++;
        }
        

        if (objPoint.next) {
            point.next = this.createRoadPoint(objPoint.next, parent);
        }

        return nodeRoadPoint;
    }

    triggerFinished (type) {
        console.log(`build ${type} finished!`);

        let tips = '';
        switch (type) {
            case 'plane':
                    tips = i18n.t('fightMap.trimTheGround');
                break;
            case 'road':
                    tips = i18n.t('fightMap.pavingTheRoad');
                break;
            case 'tree':
                    tips = i18n.t('fightMap.plantingTree');
                break;
            case 'house':
                    tips = i18n.t('fightMap.decorateHouse');
                break;
            case 'sign':
                    tips = i18n.t('fightMap.paintLandmarks');
                break;
        }

        if (tips) {
            clientEvent.dispatchEvent('updateLoading', 10, tips);
        }

        this.curProgress++;
        if (this._progressListener) {
            this._progressListener(this.curProgress, this.maxProgress);
        }

        if (this.curProgress >= this.maxProgress && this._completeListener) {
            this._completeListener();
        }
    }

    recycle () {
        console.log('recycle map elements...');

        this.recycleModel('plane');
        this.recycleModel('road');
        this.recycleModel('tree');
        this.recycleModel('house');
        this.recycleModel('sign');
        
        //路径属于空节点挂脚本，直接做清除操作
        this.node.removeAllChildren();
    }

    recycleModel (type) {
        let nodeParent = this.node.getChildByName(type);
        if (!nodeParent) {
            return;
        }

        for (let idx = 0; idx < nodeParent.children.length; idx++) {
            let child = nodeParent.children[idx];
            poolManager.instance.putNode(child);
        }
    }

    // update (deltaTime: number) {
    //     // Your update function goes here.
    // }
}
